#! /usr/bin/env python3
# -*- coding:utf-8 -*-

'多进程多线程'
import os
import time
import random
from multiprocessing import Process, Queue
from multiprocessing import Pool
import subprocess
import threading


def run_c(name):
    print("进程名称：%s，进程id：%s" % (name, os.getpid()))


def testThread():
    print("主进程id：%s" % os.getpid())
    print("即将打开子进程")
    p = Process(target=run_c, args=('ceshi1',))
    p.start()
    p.join()   # 等待子进程结束后再执行，用于进程同步
    print("进程结束")


def processPool(name):
    print("进程名称：%s-进程id：%s" % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print("进程名称:%s-进程id:%s耗时：%.2fs" % (name, os.getpid(), end - start))


def testPool():
    print("主进程", os.getpid())
    p = Pool(4)
    for i in range(10):
        p.apply_async(processPool, args=('p' + str(i),),)
    print("等待子进程结束")
    p.close()
    p.join()  # pool调用join前必须调用close方法
    print("全部进程已结束")


def subTest():
    print("subprocess执行")
    r = subprocess.call(['nslookup', 'www.baidu.com'])
    print("exit:", r)


# subTest()


def subTest2():
    print("subprocess执行2")
    p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, err = p.communicate(input=b'set q=mx\nbaidu.com\nexit\n')
    print(output.decode('gbk'), err.decode("gbk"))  # 中文路径导致只能用gbk
    print("exit:", p.returncode)


# subTest2()


# 读写Queue
def write(q, plist):
    print("进程(id:%s)开始写入" % os.getpid())
    for i in plist.items():
        print("Queue添加", i)
        q.put(i)
        time.sleep(random.random())


def read(q):
    print("进程(id：%s)开始读取" % os.getpid())
    while True:
        print("Queue读取", q.get(True))


def testWriteRead():
    q = Queue()
    qw = Process(target=write, args=(q, dict(name='dean', age=20)))
    qr = Process(target=read, args=(q,))
    qw.start()
    qr.start()
    qw.join()
    qr.terminate()   # 手动终止


# 必须要在 __name__ == '__main__'中才能执行
# if __name__ == '__main__':
    # testThread()
    # testPool()
    # testWriteRead()


# 多线程
balance = 0
# threadLocal
local = threading.local()
lock = threading.Lock()


def change(x):
    print("读取threadLocal:", local.threadParam)
    global balance
    print("线程%s执行第%d次" % (threading.currentThread().name, x))
    balance = balance + x
    balance = balance - x
    # print("线程%s执行第%d次值：%d" % (threading.currentThread().name, x, balance))
    # time.sleep(random.random())


def loop(n):
    print("线程%s执行值：%d" % (threading.currentThread().name, balance))
    local.threadParam = str(n)
    for x in range(5):
        lock.acquire()
        try:
            change(x)
        finally:
            lock.release()
    print("线程%s结束值：%d" % (threading.currentThread().name, balance))


def multiThread():
    print("线程%s执行值：%d" % (threading.currentThread().name, balance))
    t1 = threading.Thread(target=loop, name='loopThread1', args=(5,))
    t2 = threading.Thread(target=loop, name='loopThread2', args=(8,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("线程%s结束值：%d" % (threading.currentThread().name, balance))


multiThread()
